package com.wuliu.system.service.app.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wuliu.common.constant.Constants;
import com.wuliu.common.constant.OrderConstants;
import com.wuliu.common.core.domain.PageResult;
import com.wuliu.common.core.domain.entity.SysAppletUser;
import com.wuliu.common.exception.ServiceException;
import com.wuliu.common.utils.DateUtils;
import com.wuliu.common.utils.RedissonUtils;
import com.wuliu.common.utils.SecurityUtils;
import com.wuliu.system.domain.TspOrderPre;
import com.wuliu.system.domain.bo.CalcOrderFeeBo;
import com.wuliu.system.domain.dto.app.BatchCollectOrderDto;
import com.wuliu.system.domain.dto.app.CalcOrderFeeDto;
import com.wuliu.system.domain.dto.app.RecOrderPreDto;
import com.wuliu.system.domain.dto.app.UserOrderPreDto;
import com.wuliu.system.domain.vo.applet.TspOrderPreVo;
import com.wuliu.system.mapper.TspOrderPreMapper;
import com.wuliu.system.service.CommonService;
import com.wuliu.system.service.app.AppTspOrderPreService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author realue
 * @version 1.0
 * @date 2023-11-03 17:44
 */
@Service
public class AppTspOrderPreServiceImpl extends ServiceImpl<TspOrderPreMapper, TspOrderPre> implements AppTspOrderPreService {
    @Resource
    private TspOrderPreMapper tspOrderPreMapper;
    @Resource
    private RedissonUtils redissonUtils;
    @Resource
    private CommonService commonService;

    /**
     * 查询当前业务员的预约单
     *
     * @param dto
     * @return
     */
    @Override
    public PageResult<TspOrderPreVo> getOrderPres(UserOrderPreDto dto) {
        SysAppletUser user = SecurityUtils.getAppletUser();
        Map<String, Object> map = new HashMap<>();
        map.put("sysAccount", user.getSysAccount());
        map.put("status", dto.getStatus());
        map.put("lng", dto.getLng());
        map.put("lat", dto.getLat());
        map.put("beginTime", dto.getBeginTime());
        map.put("endTime", dto.getEndTime());
        map.put("userId", user.getUserId());
        map.put("deptId", user.getDeptId());
        Page page = PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        List<TspOrderPreVo> tspOrders = tspOrderPreMapper.selectUserOrders(map);
        return new PageResult<>(page, tspOrders);
    }

    /**
     * 预约单详细
     *
     * @param id
     * @return
     */
    @Override
    public TspOrderPre getInfo(String id) {
        return tspOrderPreMapper.selectTspOrderPreById(id);
    }

    /**
     * 接单、取消接单操作
     *
     * @param orderId
     * @param type    1.接单 2.取消接单
     * @return
     */
    @Override
    public Boolean receiveOrder(String orderId, Integer type) {
        TspOrderPre tspOrder = tspOrderPreMapper.selectOne(new LambdaQueryWrapper<TspOrderPre>().eq(TspOrderPre::getId, orderId));
        if (null == tspOrder) {
            throw new ServiceException("预约单不存在");
        }
        if (!checkStatus(tspOrder.getStatus(), type)) {
            throw new ServiceException("当前预约单状态不能操作");
        }
        SysAppletUser user = SecurityUtils.getAppletUser();
        TspOrderPre order = new TspOrderPre();
        order.setId(tspOrder.getId());
        if (type == 1) {
            boolean lockFlag;
            String redisKey = Constants.GRAB_ORDER_REDISSON_KEY + orderId;
            try {
                lockFlag = redissonUtils.tryLock(redisKey, TimeUnit.SECONDS, 5, 10);
                if (lockFlag) {
                    order.setStatus(OrderConstants.ORDER_PRE_STATUS_1);
                    order.setGrabTime(DateUtils.getTime());
                    order.setGrabUserName(user.getUserName());
                    order.setGrabUserId(user.getUserId());
                    order.setGrabUserNo(user.getUserNo());
                } else {
                    throw new ServiceException("操作失败,请重试");
                }
            } finally {
                redissonUtils.unlock(redisKey);
            }
        } else if (type == 2) {
            order.setStatus(OrderConstants.ORDER_PRE_STATUS_0);
            order.setGrabUserId(null);
            order.setGrabUserName("");
            order.setGrabTime("");
            order.setGrabUserNo("");
        }
        return tspOrderPreMapper.updateOrderForGrab(order) > 0;
    }

    /**
     * 校验证运单状态是否能操作
     *
     * @param status
     * @param type   1.接单 2.取消接单
     * @return
     */
    private Boolean checkStatus(Integer status, Integer type) {
        boolean retbool = false;
        switch (type) {
            case 1:
                retbool = status == OrderConstants.ORDER_PRE_STATUS_0;
                break;
            case 2:
                retbool = status == OrderConstants.ORDER_PRE_STATUS_1 || status == OrderConstants.ORDER_PRE_STATUS_0;
                break;
        }
        return retbool;
    }

    /**
     * 批量揽收
     *
     * @param dto
     * @return
     */
    @Override
    public Boolean batchCollect(BatchCollectOrderDto dto) {
        SysAppletUser user = SecurityUtils.getAppletUser();
        List<TspOrderPre> upOrderPre = new ArrayList<>();
        List<String> orderNos = dto.getCollectOrderItemList().stream().map(BatchCollectOrderDto.CollectOrderItem::getOrderNo).collect(Collectors.toList());
        List<TspOrderPre> tspOrderPres = tspOrderPreMapper.selectList(new LambdaQueryWrapper<TspOrderPre>()
                .eq(TspOrderPre::getSysAccount, user.getSysAccount())
                .in(TspOrderPre::getOrderNo, orderNos));
        dto.getCollectOrderItemList().forEach(t -> {
            tspOrderPres.stream().filter(k -> k.getOrderNo().equals(t.getOrderNo())).findFirst().ifPresent(one -> {
                if (one.getStatus() == OrderConstants.ORDER_PRE_STATUS_0 || one.getStatus() == OrderConstants.ORDER_PRE_STATUS_1) {
                    TspOrderPre tspOrderPre = new TspOrderPre();
                    tspOrderPre.setId(one.getId());
                    tspOrderPre.setRecTime(DateUtils.getTime());
                    tspOrderPre.setFeeAccno(dto.getFeeAccno());
                    tspOrderPre.setSrcCompName(dto.getCompName());
                    tspOrderPre.setWeight(t.getWeight());
                    tspOrderPre.setCargoName(t.getCargoName());
                    tspOrderPre.setPaySide(t.getPaySide());
                    tspOrderPre.setStatus(OrderConstants.ORDER_PRE_STATUS_2);
                    if (one.getStatus() == OrderConstants.ORDER_PRE_STATUS_0) {
                        tspOrderPre.setGrabUserTel(user.getMobile());
                        tspOrderPre.setGrabUserNo(user.getUserNo());
                        tspOrderPre.setGrabTime(DateUtils.getTime());
                        tspOrderPre.setGrabUserName(user.getUserName());
                        tspOrderPre.setGrabUserId(user.getUserId());
                    }
                    upOrderPre.add(tspOrderPre);
                }
            });
        });
        return this.updateBatchById(upOrderPre);
    }

    /**
     * 单票揽收
     *
     * @param dto
     * @return
     */
    @Override
    public Boolean collect(RecOrderPreDto dto) {
        SysAppletUser user = SecurityUtils.getAppletUser();
        TspOrderPre tspOrderPre = tspOrderPreMapper.selectOne(new LambdaQueryWrapper<TspOrderPre>()
                .eq(TspOrderPre::getSysAccount, user.getSysAccount())
                .eq(TspOrderPre::getOrderNo, dto.getOrderNo()));
        BeanUtil.copyProperties(dto, tspOrderPre);
        tspOrderPre.setUpdateTime(DateUtils.getNowDate());
        tspOrderPre.setStatus(OrderConstants.ORDER_PRE_STATUS_2);
        tspOrderPre.setRecTime(DateUtils.getTime());
        return tspOrderPreMapper.updateTspOrderPre(tspOrderPre) > 0;
    }

    /**
     * 计算运费
     *
     * @param dto
     * @return
     */
    @Override
    public BigDecimal calcFee(CalcOrderFeeDto dto) {
        SysAppletUser user = SecurityUtils.getAppletUser();
        CalcOrderFeeBo calcOrderFeeBo = new CalcOrderFeeBo();
        BeanUtil.copyProperties(dto, calcOrderFeeBo);
        if (Objects.isNull(dto.getCargoType())) {
            dto.setCargoType(OrderConstants.ORDER_CARGO_TYPE_1);
        }
        calcOrderFeeBo.setSysAccount(user.getSysAccount());
        return commonService.calcFee(calcOrderFeeBo);
    }
}
